from rest_framework import serializers

from goods.models import SKU, SKUSpecification, GoodsCategory, SPUSpecification, SpecificationOption
from django.db import transaction
from celery_tasks.static_html.tasks import get_detail_html


class SKUSpecificationSerializer(serializers.ModelSerializer):
    """
        SKU具体规格表序列化器
    """
    spec_id = serializers.IntegerField()
    option_id = serializers.IntegerField()

    class Meta:
        # 指定生成序列化字段的模型类
        model = SKUSpecification
        # 指定字段
        fields = ('spec_id', 'option_id')


class SKUSerializer(serializers.ModelSerializer):
    """
        商品SKU序列化器

    """
    # sku作为子表嵌套返回父表spu和category
    # 关联嵌套序列化返回StringRelatedField返回关联表的str的内容
    category = serializers.StringRelatedField(read_only=True)
    spu = serializers.StringRelatedField(read_only=True)
    # 数据库外键是加id的
    # spu=serializers.PrimaryKeyRelatedField()
    spu_id = serializers.IntegerField()
    category_id = serializers.IntegerField()
    # sku作为父表嵌套返回子表SKUSpecification
    specs = SKUSpecificationSerializer(many=True)

    class Meta:
        # 指定生成序列化字段的模型类
        model = SKU
        # 指定字段
        fields = "__all__"

    # @transaction.atomic()
    def create(self, validated_data):
        # 涉及多张表操作引入事务
        # 开启事务
        with transaction.atomic():
            # 设置保存点
            save_point = transaction.savepoint()
            try:
                # 保存sku表
                # 取出specs字段
                specs = validated_data.get('specs')
                # 将specs字段从validated_data删除
                del validated_data['specs']
                sku = SKU.objects.create(**validated_data)
                # 保存sku具体规格表
                for spec in specs:
                    SKUSpecification.objects.create(sku=sku, spec_id=spec['spec_id'], option_id=spec['option_id'])
            except:
                transaction.savepoint_rollback(save_point)
                raise serializers.ValidationError('数据保存失败')

            transaction.savepoint_commit(save_point)
            # 静态化生成新的详情页面
            get_detail_html.delay(sku.id)
            return sku

    def update(self, instance, validated_data):
        # 涉及多张表操作引入事务
        # 开启事务
        with transaction.atomic():
            # 设置保存点
            save_point = transaction.savepoint()
            try:
                # 更新sku表
                # 取出specs字段
                specs = validated_data.get('specs')
                # 将specs字段从validated_data删除
                del validated_data['specs']
                SKU.objects.filter(id=instance.id).update(**validated_data)
                # 更新sku具体规格表
                for spec in specs:
                    SKUSpecification.objects.filter(sku=instance,spec_id=spec['spec_id']).update(option_id=spec['option_id'])
            except:
                transaction.savepoint_rollback(save_point)
                raise serializers.ValidationError('数据保存失败')

            transaction.savepoint_commit(save_point)
            # 静态化生成新的详情页面
            get_detail_html.delay(instance.id)
            return instance



class GoodsCategorySerializer(serializers.ModelSerializer):
    """
        商品分类
    """

    class Meta:
        # 指定生成序列化字段的模型类
        model = GoodsCategory
        # 指定字段
        fields = "__all__"


class SpecificationOptionSerializer(serializers.ModelSerializer):
    """
               商品SPU规格选项
    """

    class Meta:
        # 指定生成序列化字段的模型类
        model = SpecificationOption
        # 指定字段
        fields = ('id', 'value')


class SPUSpecificationSerializer(serializers.ModelSerializer):
    """
            商品SPU规格
        """

    spu = serializers.StringRelatedField(read_only=True)
    spu_id = serializers.IntegerField()

    options = SpecificationOptionSerializer(many=True)

    class Meta:
        # 指定生成序列化字段的模型类
        model = SPUSpecification
        # 指定字段
        fields = "__all__"
